/**
 * 基本数据类型
*/
let str: string = 'str';
let bool: boolean = false;
let num: number = 1;

// 变量名:元素类型[]
let arr: string[] = ['1']

/**
 * 元组类型：Tuple
*/
let tupleType: [string, boolean]; // 定义一个Tuple类型,其中的元素的类型必须一个是string，一个时boolean
tupleType = ['1', true];
// tupleType = ['1','2',true]; Type 'string' is not assignable to type 'boolean'
// tupleType = ['1'] Type '[string]' is not assignable to type '[string, boolean]'.
//  Source has 1 element(s) but target requires 2.

//const sym = Symbol();

// 枚举,数字可以不进行初始化操作，字符串必须要进行初始化操作
enum A {

}

// 常量枚举
const enum B {

}
/**
 * 顶级类型之一：any:
 * 对any类型的值可以进行任何的操作，而无需事先执行任何形式的检查
 * 但是如果使用了any类型，就无法使用ts的保护机制
*/
let anyVal: any;
//anyVal.arr; OK
//anyVal.fn(); OK

/**
 * 顶级类型之二：unknown，所有的类型都可以赋值给unknown，
 * 但是unknown类型的变量只能赋值给any/unknown，为什么？只有任意类型的值才可以存储任意类型的值
 *
 * 与any的不同是，unknown不能够对值进行任何操作
*/
let unknownVal: unknown = 1;
// Type 'unknown' is not assignable to type 'string'.
// str = unknownVal
// Property 'arr' does not exist on type 'unknown'
// unknownVal.arr;

/**
 * void类型
*/
// 1. 声明函数的返回值
function fn(): void { }
// 声明为void的变量，在严格模式下其值只能是undefined
let voidVal: void;

/**
 * object类型,表示非原始类型
*/
let obj: object = {};
console.log(obj); // 打印出一个Object对象
// obj.a = 1; Property 'a' does not exist on type 'object'
/* obj = null;
obj = undefined; */
// obj = 123 Type 'number' is not assignable to type 'object'.

/**
 * Object类型，表示的是对象类型，可以直接调用对象原型上的方法
*/
let obj3: Object;
obj3.hasOwnProperty('a')
// obj3.b = 2; Property 'b' does not exist on type 'Object'.

/**
 * {}类型，描述了一个没有成员的对象，所以直接obj4.a会报错
 * 但是仍然可以使用对象原型中定义的方法
*/
let obj4: {};
// obj4.a = 1; Property 'a' does not exist on type '{}'
console.log(obj4.toString());

/**
 * never类型
 * 1. 函数的返回值类型为never
 * A function returning 'never' cannot have a reachable end point.
 * 代表着函数必须没有尽头
 * 2. 代表一个不可能有值的变量
*/
let v:never;
 // v = 1 Type 'number' is not assignable to type 'never'.
function fn2(): never {
    throw 'error'
}
function fn3(): never {
    while (true) { }
}

// 定义一个type
type Foo = string | boolean;
// 使⽤ never 避免出现新增了联合类型没有对应的实现，⽬的就是写出类型绝对安全的代码
function fn4(foo:Foo){
    if(typeof foo === 'string'){

    }else if(typeof foo === 'boolean'){

    }else{
        const checkType:never = foo;
    }
}
// 这里的作用时：当有一天Foo类型扩展为string | boolean | number时，
// 就可以通过else分支里的checkType报错来提示number